package com.garen.common;

import java.io.IOException;
import java.util.*;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;

import com.garen.utils.CommonUtils;
import com.garen.utils.FilterUtils;


/*
 * 系统过滤器
 * 实现权限拦截
 * 基本日志记录
 */
abstract public class AbstractFilter implements Filter {

	protected  Log log = LogFactory.getLog(this.getClass());
	private static ServletContext sc;
	public static final String INST = "INST";//当前实例
	
	public static final String FILTER_OK = "OK";//当前实例
	public static final String FILTER_GO = "GO";//当前实例
	
	//权限过滤器
	public List<IAuthFilter> filterList = new ArrayList<IAuthFilter>();
	
	//注册过滤器
	public void regFilter(IAuthFilter authFilter){
		if(authFilter != null)
			filterList.add(authFilter);
	}
	
	//线程安全变量,即不同线程获取不同实例
	private static ThreadLocal<MsgBean> threadMbean    = new ThreadLocal<MsgBean>();   
	private static ThreadLocal<HttpServletRequest> threadRequest  = new ThreadLocal<HttpServletRequest>();   
	private static ThreadLocal<HttpServletResponse> threadResponse = new ThreadLocal<HttpServletResponse>();   
	
	//spring上下文管理程序
	private static WebApplicationContext wx;
	
	//初始化servlet request response
	public static MsgBean in(HttpServletRequest httprequest,HttpServletResponse httpresponse){
		threadRequest.set(httprequest);
		threadResponse.set(httpresponse);
		return  getMsgBean();
	}
	
	//清除
	public static void out(){
		threadMbean.remove();
		threadRequest.remove();
		threadResponse.remove();
	}
	
	/*
	 * 过滤请求
	 */
	public void doFilter(ServletRequest request, ServletResponse response,
			FilterChain chain) throws IOException, ServletException {
		HttpServletRequest httprequest = (HttpServletRequest)request;
		HttpServletResponse httpresponse = (HttpServletResponse)response;
		MsgBean  mbean = in(httprequest, httpresponse);
		String ret = null;
		String ctrluri = FilterUtils.filterUri(httprequest);
		if(ctrluri == null) {//静态资源直接放过去
			chain.doFilter(request, response);
			return;
		}
		String requesttype = FilterUtils.getAcceptType(httprequest);//请求文档类型 JSP JSON XML
		long d1 = System.currentTimeMillis();
		log.warn("IN=" + ctrluri + "=" + request.getRemoteAddr() 
				+ ":" + request.getRemotePort() + "="+ httprequest.getSession().getId());
		try{
			for(IAuthFilter f : filterList){
				ret = f.doFilter(mbean, httprequest,
						httpresponse, chain);
				if(FILTER_OK.equals(ret)) {
					chain.doFilter(request, response);
					break;
				}else if(FILTER_GO.equals(ret)) continue;
				else break;
			}
		}catch(Exception ex){
			ret = "EXCEPTION";
			mbean.setRetInfo(-501, "发生异常 !" + ex.getMessage());
			log.error(CommonUtils.log4stack(ex));//异常信息到页面
		}
		if("OK".equals(ret) == false){
			if("JSP".equals(requesttype)){
				request.setAttribute("mbean", mbean);
				String forwardurl = "/WEB-INF/sys/error.jsp";
				httprequest.getRequestDispatcher(forwardurl)
						.forward(request, response);
			}else{//json格式
				AbstractAction.Json(mbean);
			}
		}
		long d2 = System.currentTimeMillis();
		log.warn("OUT=" + ctrluri +"=" + (d2 - d1) + "ms=" 
				+ ret + "="+ mbean.getInfo());
		out();
	}
	
	public static HttpServletRequest getRequest(){
		return threadRequest.get();
	}
	
	public static HttpServletResponse getResponse(){
		return threadResponse.get();
	}
		
	public static HttpSession getSession(){
		HttpServletRequest request = threadRequest.get();
		if(request == null) return null;
		return request.getSession();
	}
	
	public static MsgBean getMsgBean(){
		MsgBean mbean = threadMbean.get();
		if(mbean == null){
			mbean = new MsgBean();
			threadMbean.set(mbean);
		}
		return mbean;
	}
	
	public static MsgBean getMsgBean(int id,String info){
		MsgBean mbean = getMsgBean();
		mbean.setRetInfo(id,info);
		return mbean;
	}
	
	public static MsgBean getMsgBean(boolean debug){
		MsgBean mbean = getMsgBean();
		return mbean;
	}
	/*
	 * 初始化时执行
	 */
	public void init(FilterConfig fc) throws ServletException {
		sc = fc.getServletContext();
		wx = WebApplicationContextUtils
				.getRequiredWebApplicationContext(fc.getServletContext());
		fc.getServletContext().setAttribute(INST, this);//保存当前实例
		for(IAuthFilter f : filterList){
			f.init(fc);
		}
	}
	
	//获取当前过滤器的实例
	public static AbstractFilter getInstance(){
		return (AbstractFilter)getSession().getServletContext().getAttribute(INST);
	}
	
	/*
	 * 销毁时执行
	 */
	public void destroy() {
		for(IAuthFilter f : filterList){
			f.destroy();
		}
	}
	
	//根据名称获取spring实例化的对象
	public static Object getSpringBean(String beanName){
		try{
			return (wx==null)?null:wx.getBean(beanName);
		}catch (NoSuchBeanDefinitionException e) {
		}
		return null;
	}
	
	@SuppressWarnings("unchecked")
	public static <T>T getSpringBean(String beanName,Class<? extends Object> T){
		Object obj = getSpringBean(beanName);
		return obj == null?null:(T)obj;
	}
	

	public static ServletContext getSc() {
		return sc;
	}
	
	//获取资源绝对路径
	public static String getRealPath(String path){
		return sc == null?null:sc.getRealPath(path);
	}

}
